﻿using BatchPrint.Extensions;
using BatchPrint.Models;
using BatchPrint.Services;
using BatchPrint.Windows;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Win32;
using System.Collections.ObjectModel;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace BatchPrint;

public partial class MainWindowViewModel : ObservableObject
{
    public string Title => $"批量打印程序（打印机：{SelectPrinter}）";

    private readonly Dictionary<string, PrintModel> _cache;

    [ObservableProperty]
    private ObservableCollection<FileModel> _fileList;

    [ObservableProperty]
    private Image? _image;

    [ObservableProperty]
    private SelectionMode _mode;

    [ObservableProperty]
    private List<string> _printerList;

    [ObservableProperty]
    [NotifyPropertyChangedFor(nameof(Title))]
    private string _selectPrinter;

    private readonly PrinterManager _printManager;
    private readonly ConverterProvider _converterProvider;

    public Grid? Container { get; set; }

    private bool _isKeyDown;

    public MainWindowViewModel(PrinterManager printerManager, ConverterProvider converterProvider)
    {
        _cache = [];
        _converterProvider = converterProvider;
        _printManager = printerManager;
        PrinterList = [.. _printManager.GetAvailablePrinters()];
        SelectPrinter = _printManager.GetDefaultPrinter();
        FileList = [];
    }

    [RelayCommand]
    private void OpenFileDialog()
    {
        OpenFileDialog dialog = new OpenFileDialog();
        dialog.Title = "选择文件";
        dialog.Multiselect = true;
        dialog.Filter = "(*.jpg,*.png,*.jpeg,*.bmp,*.gif,*.pdf,*.xlsx)|*.jpg;*.png;*.jpeg;*.bmp;*.gif;*.pdf;*.xlsx|All files(*.*)|*.*";
        var result = dialog.ShowDialog();
        if (result == true)
        {
            foreach (var filePath in dialog.FileNames)
            {
                FileList.Add(new FileModel
                {
                    FieldId = Guid.NewGuid().ToString(),
                    FileName = Path.GetFileName(filePath),
                    FilePath = filePath,
                    FileType = _converterProvider.GetFileType(filePath),
                });

            }
        }
    }

    [RelayCommand]
    private void DeleteField(string fieldId)
    {
        var list = FileList.Where(x => x.IsSelected).ToList();
        foreach (var item in list)
            FileList.Remove(item);
    }

    /// <summary>
    /// 打印画布图片
    /// </summary>
    /// <returns></returns>
    [RelayCommand]
    private void Print()
    {
        if (Container != null)
        {
            var fileName = Path.GetTempFileName();
            TakeScreenshot(Container, fileName);

            StartPrint([new PrintModel() {
                FilePath = fileName ,
                Image = DImage.FromFile(fileName)
            }]);
        }
    }

    /// <summary>
    /// 打印所选文件
    /// </summary>
    /// <returns></returns>
    [RelayCommand]
    private async Task PrintBatch()
    {
        var prints = new List<PrintModel>();
        var files = FileList.Where(x => x.IsSelected).ToList();
        foreach (var item in files)
        {
            if (item.Image != null)
            {
                prints.Add(new PrintModel()
                {
                    FilePath = item.FilePath,
                    Image = item.Image
                });
            }
            else
            {
                var image = await _converterProvider
                            .GetConverter(item.FilePath)
                            .Convert(item.FilePath);
                prints.Add(new PrintModel()
                {
                    FilePath = item.FilePath,
                    Image = image
                });
            }
        }
        StartPrint(prints);
    }

    /// <summary>
    /// 将画布上的图片保存到文件
    /// </summary>
    /// <returns></returns>
    [RelayCommand]
    private void SaveImage()
    {
        if (Container != null)
        {
            SaveFileDialog dialog = new SaveFileDialog();
            if (dialog.ShowDialog() == true)
            {
                TakeScreenshot(Container, dialog.FileName);
            }
        }
    }

    /// <summary>
    /// 将所选文件添加到画布
    /// </summary>
    /// <returns></returns>
    [RelayCommand]
    private void AddFileToCanvas() =>
        RenderContainer();

    [RelayCommand]
    private void ClearCanvas()
    {
        RenderContainer();
    }

    private void StartPrint(List<PrintModel> prints)
    {
        var progress = App.Current.ServiceProvider.GetRequiredService<ProgressWindow>();
        ProgressWindowViewModel progressVm = (progress.DataContext as ProgressWindowViewModel)!;
        progressVm.OnPrintFinish += OnPrintFinish;

        var printModels = new List<PrintModel>();
        foreach (var file in prints)
        {
            printModels.Add(file);
        }

        progress.StartPrint(prints, SelectPrinter);
    }

    private void OnPrintFinish()
    {

    }

    public void WindowSizeChanged(object sender, SizeChangedEventArgs e)
    {
        //var element = (Container!.Parent as FrameworkElement);
        //if (element != null)
        //{
        //    Canvas.Height = 2000; //element.ActualHeight;
        //    Canvas.Width = Canvas.ActualHeight * 0.7;

        //    Canvas.Children.Clear();
        //    for (var index = 0; index < _images.Count; index++)
        //    {
        //        var image = _images[index];
        //        var row = (index / 3);
        //        var column = index % 3;
        //        image.Margin = new Thickness(10, 10, 10, 10);
        //        image.Width = (Canvas.ActualWidth / 3) - 20;
        //        image.Height = (Canvas.ActualHeight / 2) - 20;
        //        Canvas.SetLeft(image, column * image.ActualWidth);
        //        Canvas.SetTop(image, row * image.ActualHeight);

        //        Canvas.Children.Add(image);
        //    }
        //}
    }

    public async void RenderContainer()
    {
        if (Container == null) return;

        Container.Children.Clear();
        Container.RowDefinitions.Clear();
        Container.ColumnDefinitions.Clear();
        ImageSourceConverter imageSource = new();
        if (FileList.Where(x => x.IsSelected).Count() == 1)
        {
            if (_isKeyDown == false)
            {
                var file = FileList.FirstOrDefault(x => x.IsSelected);
                if (file != null)
                {
                    if (file.Image == null)
                    {
                        var image = await _converterProvider
                            .GetConverter(file.FilePath)
                            .Convert(file.FilePath);
                        file.Image = image;
                    }

                    Container.Children.Add(new Image
                    {
                        Source = file.Image.ConvertToBitmapImage()
                    });
                }
            }
        }
        else if (FileList.Where(x => x.IsSelected).Count() > 1)
        {
            Container.RowDefinitions.Add(new RowDefinition());
            Container.RowDefinitions.Add(new RowDefinition());

            Container.ColumnDefinitions.Add(new ColumnDefinition());
            Container.ColumnDefinitions.Add(new ColumnDefinition());
            Container.ColumnDefinitions.Add(new ColumnDefinition());


            var list = FileList.Where(x => x.IsSelected).ToList();
            for (var index = 0; index < list.Count; index++)
            {
                if (imageSource.ConvertFromString(list[index].FilePath) is ImageSource source)
                {
                    var image = new Image()
                    {
                        Source = source,
                        Margin = new Thickness(5)
                    };
                    Container.Children.Add(image);
                    var row = (index / 3);
                    var column = index % 3;
                    Grid.SetRow(image, row);
                    Grid.SetColumn(image, column);
                }
            }
        }
    }

    public void WindowKeyChange(object sender, KeyEventArgs e)
    {
        if (e.IsUp && e.Key == Key.LeftCtrl)
        {
            _isKeyDown = false;
        }
        else if (e.IsDown && e.Key == Key.LeftCtrl)
        {
            Mode = SelectionMode.Multiple;
            _isKeyDown = true;
        }
    }

    public void WindowSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (_isKeyDown == false)
        {
            Mode = SelectionMode.Single;
            RenderContainer();
        }
    }

    public static void TakeScreenshot(FrameworkElement element, string fileName)
    {
        var renderTarget = new RenderTargetBitmap(
            (int)element.ActualWidth,
            (int)element.ActualHeight,
            96, 96, PixelFormats.Pbgra32);

        var visual = new DrawingVisual();
        using (var context = visual.RenderOpen())
        {
            context.DrawRectangle(
                new VisualBrush(element),
                null,
                new Rect(0, 0, element.ActualWidth, element.ActualHeight));
        }

        renderTarget.Render(visual);

        var bitmapFrame = BitmapFrame.Create(renderTarget);
        var encoder = new PngBitmapEncoder();
        encoder.Frames.Add(bitmapFrame);
        using var stream = File.Create(fileName);
        encoder.Save(stream);
    }
}
